/*
 * Author: vdaras
 */

#include "../sdl/SDLException.h"
#include "../sdl/TextImage.h"
#include "Label.h"
#include "Exception.h"
#include "Container.h"

namespace gui
{

/**
 * Constructor initializes the Component part of the Label and the font which
 * the label uses to render its' text. After member initialization the constructor
 * allocates a surface and creates the display part of the Label.
 *
 * @param name: name of the Label Component
 * @param w: width of the Label
 * @param h: height of the Label
 * @param text: Label's text
 * @param txtColor: Label's text color
 * @param fnt: font used by the Label to render its' text
 */

Label::Label(const std::string &name, int w, int h, const std::string &text, const sdl::Color &txtColor, Resource<sdl::Font> *fnt)
:
Component(name, w, h),
m_text(text),
m_txtColor(txtColor),
m_fontRes(fnt),
m_textDisplay(NULL)
{
    m_font = m_fontRes->GetRawData( );
    
    //render text, if failed
    if(!RenderText())
    {
        //indicate that an error occurred during text rendering
        throw gui::Exception("Label could not be created!");
    }
}


/**
 * Constructor initializes the Component part of the Label and the font, text and text color
 * which the label uses to render itself. After member initialization the constructor
 * allocates a surface and creates the display part of the Label. It also adds the
 * Label to the passed Container @x,y position.
 *
 * @param name: name of the Label Component
 * @param w: width of the Label
 * @param h: height of the Label
 * @param text: Label's text
 * @param txtColor: Label's text color
 * @param fnt: font used by the Label to render its' text
 */

Label::Label(const std::string &name, Container *parent, int x, int y, int w, int h, const std::string &text, const sdl::Color &txtColor, Resource<sdl::Font> *fnt)
:
Component(name, parent, x, y, w, h),
m_text(text),
m_txtColor(txtColor),
m_fontRes(fnt),
m_textDisplay(NULL)
{
    m_font = m_fontRes->GetRawData( );
    
    //render text, if failed
    if( !RenderText( ) )
    {
        //indicate that an error occurred during text rendering
        throw gui::Exception( "Label could not be created!" );
    }
}

Label::~Label()
{
    m_fontRes->DecreaseReference( );
}


/** 
 * Resizes this label.
 *
 * @param width: new width.
 * @param height: new height.
 */

void Label::Resize(int width, int height)
{
    
}


/**
 * Sets the text of the label.
 *
 * @param text: the new text
 */

void Label::SetText(const std::string& text)
{
    m_text = text;
    RenderText( );
}


/**
 * Sets the color of the label's text.
 *
 * @param color: the new color
 */

void Label::SetTextColor(const sdl::Color& txtColor)
{
    m_txtColor = txtColor;
    RenderText( );
}


/**
 * Sets the font of the label's text. The font is not owned by the Label and
 * it's client code's responsibility to manage it's memory.
 *
 * @param fnt: the new font
 */

void Label::SetFont(Resource<sdl::Font>* fnt)
{
    m_fontRes->DecreaseReference( );
    m_fontRes = fnt;
    m_fontRes->IncreaseReference( );
    m_font = m_fontRes->GetRawData( );
    RenderText( );
}


/**
 * Draws the label on a surface.
 *
 * @param target: the target surface.
 */

void Label::Draw(sdl::Surface* target) const
{
    m_textDisplay->Blit( GetX( ), GetY( ), target, &m_visiblePart );
}


/**
 * Updates the label.
 */

void Label::Update()
{
}


/**
 * This routine renders the graphical part of the Label using the text and color
 * members. Returns failure if an error occurs during rendering.
 *
 * @return a boolean value indicating if text rendering was successful or not.
 */

bool Label::RenderText()
{
    try
    {
        //allocate a temporary canvas based on the Label's dimensions
        std::auto_ptr< sdl::Canvas > tempDisplay( new sdl::Canvas( GetWidth( ), GetHeight( ) ) );

        //render text on the temporary surface
        m_font->RenderText( 0, 0, m_text, m_txtColor, tempDisplay.get( ) );

        //set the Label's display as the temporary canvas
        m_textDisplay = tempDisplay;
    }
    catch(sdl::Exception &exc)
    {
        //an error occured, return failure
        return false;
    }

    //return success
    return true;
}

};
